
/*
**************************************************************************************************************
File:         interface.sv
Description:  Defines the interface between the DDR controller and the DDR memory stub
Author     :  Rohit Kulkarni
**************************************************************************************************************
*/
`include "package.sv"
/*
//----- DEFINES ----------
parameter DATA_WIDTH  = 72;       //64 bits for data + 8 bits for ECC
parameter ADDR_WIDTH  = 17;       //17 bit address consisting of 14 bit row/column address + 3 bit bank address
parameter BANK_ADDR_WIDTH = 3;    //3 bit bank address
parameter ROW_WIDTH = 7;
parameter COL_WIDTH = 7;
parameter BANK_END = ADDR_WIDTH - BANK_ADDR_WIDTH;   //lowest bit = 14
parameter ROW_END = BANK_END - ROW_WIDTH;  	 //lowest bit = 7
parameter LOW   = 1'b0;
parameter HIGH  = 1'b1;
parameter REFRESH_COUNT_WIDTH = 20;
parameter REFRESH_COUNT_LIMIT = 10'd780; 
*/

/*----- Calculation of refresh count limit ----------
  Refresh interval = 7.8us
  Assuming CK = 100MHz ==> Fck = 0.01us 
  Refresh count limit  = 7.8us / 0.01 us  = 780
*/

/*----- SIGNAL DEFINITIONS -------------

  CK, CK_bar: DIFFERENTIAL CLOCK SIGNALS
  CKE    : CLOCK ENABLE 
  ADDR   : ADDRESS INPUTS
  DQ     : BIDIRECTIONAL DATA (INPUT/OUTPUT)
  CS     : CHIP SELECT
  RAS    : ROW ADDRESS STROBE 
  CAS    : COLUMN ADDRESS STROBE
  WE     : WRITE ENABLE
  DQS    : DATA STROBE
*/

interface DDR_bus(input logic CK);
  wire  [DATA_WIDTH-1:0]  DQ;
  wire  [ADDR_WIDTH-1:0]  addr;
  logic CKE;
  logic RAS;
  logic CAS;
  logic WE;
  logic CS;       
  logic DQS;
  

  //Modport for the memory controller
 modport memory_controller
  (
    //Import tasks   
    import  activate,
    import  precharge,
    import  precharge_all,
    import  refresh,
    import  start_refresh_count,
      
    //Signals for the memory controller  
    input CK,
    inout DQ,
    output addr,
    output CKE,
    output RAS,
    output CAS,
    output WE,
    output CS,
    output DQS
  );

  //Modport for the memory stub
  modport memory_stub
  (
    inout DQ,
    input addr,
    input CKE,
    input RAS,
    input CAS,
    input WE,
    input CS,
    input DQS
  );


  //this should go in a package. do we want to use more commands?
  typedef enum {REF, PRE, PREA, ACT, WR, RD, NOP, DES} commands;

  
  //Internal signals
  logic [REFRESH_COUNT_WIDTH-1:0] refresh_count;
  
  
/*
  Task       : en_chip
  Description: Enables the memory stub by deasserting the active low chip select signal
*/  
  task en_chip();
   // always_ff @(posedge CK)
    begin
      CS  <= LOW;
   end 
  endtask
  
/*
  Task       : activate
  Description: Activates the bank indicated by the argument of the task 
               The bank address on the address lines determines the bank to activate 
*/  
  task activate(input [ROW_END-1:BANK_END] bank, input [LOGICAL_ADDR_WIDTH-1:ROW_END] row);   //NEED TIMING PARAMETERS
	   //ACT <= HIGH;
   	//always_ff @(CK)
   	begin
   	  CS <= LOW;
   	  @(posedge CK) RAS  <= LOW;
	    @(posedge CK) CAS <= LOW;
    	 @(posedge CK) RAS  <= HIGH;
 	 	  @(posedge CK) CAS <= HIGH;
    	 WE  <= HIGH;
    end
  endtask
  

/*
  Task       : precharge
  Description: Precharges the row to be used. precharges after Write 
  	operation for open page policy.
*/
  task precharge(input [ROW_END-1:0]ADDR);   //row passed by reference
 	//PREA <= HIGH;
	CS  <= LOW;
	RAS <= LOW;
	CAS <= HIGH;
	WE  <= LOW;
  endtask

  task precharge_all();
	//PREA <= HIGH;
	CS   <= LOW;
	RAS  <= LOW;
	CAS  <= HIGH;
	WE   <= LOW;
  endtask

/*
  Task       : refresh
  Description: Refreshes by reading the data
*/  
  task refresh();
    	RAS <= LOW;
    	CAS <= LOW;
    	WE  <= HIGH;
  endtask
  
/*
  Task       : start_refresh_count
  Description: Starts teh refresh count
*/  
  task start_refresh_count();
  
  while(refresh_count != REFRESH_COUNT_LIMIT)
  begin
    @(posedge CK)
    refresh_count = refresh_count + 1;
   end 
  
  endtask
  
  task deselect();
 	  CS <= HIGH;      //commands already underway should be unaffected
  endtask
 
endinterface
